/* The GTK+ renderer */

#include <sigc++/sigc++.h>

#include <glibmm/thread.h>

#include <gtkmm/main.h>

#include <memchart/types.hpp>

#include "main_window.hpp"
#include "object_map.hpp"

#include "gtk_data_sink.hpp"

namespace memchart
{
	/* Initialize threads before anything else */
	gtk_data_sink::thread_init::thread_init ()
	{
		Glib::thread_init();
	}


	gtk_data_sink::gtk_data_sink (const object_map & objects,
		int & argc, char ** & argv)
		: data_sink(objects),
		thread_init(),
		can_continue(false),
		gui_active(true),
		gui_thread(Glib::Thread::create(sigc::bind(
				sigc::mem_fun(*this, &gtk_data_sink::gui_func), argc, argv
			), true))
	{
		/* Wait for the other thread to create the signal dispatchers */
		Glib::Mutex::Lock lock(mutex);

		while (!can_continue)
			cond.wait(mutex);
	}

	gtk_data_sink::~gtk_data_sink ()
	{
		{
			Glib::Mutex::Lock lock(mutex);

			if (gui_active)
				signal_quit->emit();
		}

		gui_thread->join();
	}

	void gtk_data_sink::update (const string & s)
	{
		Glib::Mutex::Lock lock(mutex);

		if (gui_active)
		{
			update_msg = s;
			can_continue = false;

			signal_update->emit();

			while (!can_continue)
				cond.wait(mutex);
		}
	}

	/* The main function for the GUI thread */
	void gtk_data_sink::gui_func (int & argc, char ** & argv)
	{
		Gtk::Main kit(argc, argv);

		MainWindow window(*this);

		Gtk::Main::run(window);

		throw Glib::Thread::Exit();
	}
}
